package com.sh.rpc.protocol;

import com.sh.rpc.model.RpcRequest;
import com.sh.rpc.model.RpcResponse;
import com.sh.rpc.serializer.Serializer;
import com.sh.rpc.serializer.SerializerFactory;
import io.vertx.core.buffer.Buffer;

/**
 * 解码器
 * @author sh
 */
public class ProtocolMessageDecoder {

    // 解码
    public static ProtocolMessage<?> decode(Buffer buffer) throws Exception {
        // 从buffer取消息头
        ProtocolMessage.Header header = new ProtocolMessage.Header();
        byte magic = buffer.getByte(0);  // 取魔数
        // 判断魔数是否正确 相当于一个校验
        if (magic != ProtocolConstant.PROTOCOL_MAGIC) {
            throw new IllegalArgumentException("魔数不对，消息非法");
        }
        header.setMagic(magic);
        header.setVersion(buffer.getByte(1));
        header.setSerializer(buffer.getByte(2));
        header.setType(buffer.getByte(3));
        header.setStatus(buffer.getByte(4));
        header.setRequestId(buffer.getLong(5));
        header.setBodyLength(buffer.getInt(13));
        // **从buffer取消息体**
        byte[] bodyBytes = buffer.getBytes(17, 17 + header.getBodyLength());  // 从17开始取到17+消息体长度的字节数组
        // 根据消息体的序列化方式，反序列化消息体
        ProtocolMessageSerializerEnum serializerEnum = ProtocolMessageSerializerEnum.getEnumByKey(header.getSerializer());
        if ( serializerEnum == null) {
            throw new IllegalArgumentException("消息体序列化方式不存在，无法反序列化");
        }
                                                                // json jdk 、、、
        Serializer serializer = SerializerFactory.getInstance(serializerEnum.getValue());
        // 不同消息类型    不同的序列化方式  请求 响应 心跳 其他
        ProtocolMessageTypeEnum messageTypeEnum = ProtocolMessageTypeEnum.getEnumByKey(header.getType());
        if ( messageTypeEnum == null) {
            throw new IllegalArgumentException("消息类型不存在，无法反序列化");
        }
        switch(messageTypeEnum){
            case REQUEST:
                try {
                    RpcRequest request = serializer.deserialize(bodyBytes, RpcRequest.class);
                    return new ProtocolMessage<>(header, request);
                } catch (Exception e) {
                    throw new RuntimeException("反序列化失败, 请检查是否是请求, 请求是0， 或者检查序列化器");
                }
            case RESPONSE:
                try {
                    RpcResponse rpcResponse = serializer.deserialize(bodyBytes, RpcResponse.class);
                    return new ProtocolMessage<>(header, rpcResponse);
                } catch (Exception e) {
                    throw new RuntimeException("反序列化失败, 请检查是否是响应， 响应是1， 或者检查序列化器");
                }
            case HEART_BEAT:
            case OTHERS:
            default:
                throw new IllegalArgumentException("消息类型不存在，无法反序列化");
        }


    }
}
